package xyz.thoughtset.viewer.modules.mcp.server.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.annotation.PostConstruct;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import xyz.thoughtset.viewer.ai.mcp.server.entity.McpServerInfo;
import xyz.thoughtset.viewer.ai.mcp.server.exception.UrlConflictException;
import xyz.thoughtset.viewer.ai.mcp.server.factory.McpServerFactory;
import xyz.thoughtset.viewer.common.core.constants.StatusCodeConstant;
import xyz.thoughtset.viewer.common.crud.core.service.BaseServiceImpl;
import xyz.thoughtset.viewer.modules.datarel.entity.DataRel;
import xyz.thoughtset.viewer.modules.datarel.service.DataRelService;
import xyz.thoughtset.viewer.modules.mcp.server.constant.McpServerTopicConstant;
import xyz.thoughtset.viewer.modules.mcp.server.dao.McpServerInfoDao;

import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@Service
//@Transactional
public class McpServerInfoServiceImpl extends BaseServiceImpl<McpServerInfoDao, McpServerInfo> implements McpServerInfoService{
    @Autowired
    private McpServerFactory mcpServerFactory;
    @Autowired
    private DataRelService dataRelService;

    @PostConstruct
    public void initData() throws UrlConflictException {
        QueryWrapper<McpServerInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(McpServerInfo::getStatesCode, StatusCodeConstant.RUNNING)
                .orderByAsc(McpServerInfo::getOrderNum);
        mcpServerFactory.createMcpServer(this.list(queryWrapper));
    }


    @SneakyThrows
    @Override
    @Transactional
    public McpServerInfo saveData(McpServerInfo data) {
        if (checkNoWorking(data.getId()))
            throw new RuntimeException("entity was working");
        if (checkUnique(data)){
            throw UrlConflictException.build();
        }
        if (data.getStatesCode() == null) {
            data.setStatesCode(StatusCodeConstant.EDITING);
        }else if(StatusCodeConstant.RUNNING<=data.getStatesCode()){
            data.setStatesCode(StatusCodeConstant.EDITING);
        }
        saveOrUpdate(data);
        List<DataRel> mcpToolRels = data.getMcpToolRels().parallelStream()
                .map(e -> {
                    e.setTopic(McpServerTopicConstant.TOPIC_MCP_SERVER_TOOL);
                    return e;
                })
                .collect(Collectors.toList());
        dataRelService.saveRels(data.getId(),mcpToolRels);
        return data;
    }

    @Override
    @Transactional
    public boolean deleteById(String pkey) {
        unpublishedServer(pkey);
        return super.deleteById(pkey);
    }

    @Override
    @Transactional
    public void unpublishedServer(String serverId) {
        baseMapper.updateById(new McpServerInfo(serverId, StatusCodeConstant.EDITING));
        mcpServerFactory.closeMcpServer(serverId);
    }

    @SneakyThrows
    @Override
    @Transactional
    public void publishServer(String serverId) {
        McpServerInfo mcpServerInfo = this.getById(serverId);
        if(mcpServerInfo!=null){
            baseMapper.updateById(new McpServerInfo(serverId, StatusCodeConstant.RUNNING));
            mcpServerFactory.createMcpServer(mcpServerInfo);
        }

    }

    public boolean checkNoWorking(String serverId) {
        QueryWrapper<McpServerInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(McpServerInfo::getId, serverId)
                .eq(McpServerInfo::getStatesCode, StatusCodeConstant.RUNNING);
        return this.exists(queryWrapper);
    }
    public boolean checkUnique(McpServerInfo entity) {
        String sseUrl = entity.getSseEndpoint();
        if (StringUtils.hasText(sseUrl)) return false;
        String msgUrl = entity.getMessageEndpoint();
        if (StringUtils.hasText(msgUrl)) return false;
        QueryWrapper<McpServerInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(McpServerInfo::getSseEndpoint, sseUrl).or()
                .eq(McpServerInfo::getMessageEndpoint, msgUrl);
        if (StringUtils.hasText(entity.getId())) {
            queryWrapper.lambda().ne(McpServerInfo::getId, entity.getId());
        }
        return this.count(queryWrapper) == 0;
    }

    @Override
    public McpServerInfo selectDetail(String pkey) {
        McpServerInfo data = super.selectDetail(pkey);
        HashMap<String, List<DataRel>> groupedRelMap = dataRelService.groupRelsByPid(pkey);
        data.setMcpToolRels(groupedRelMap.get(McpServerTopicConstant.TOPIC_MCP_SERVER_TOOL));
        return data;
    }

}
